﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;
using System.Data.Objects;
using Slam.Configuration;
using Slam;
using Microsoft.SharePoint;
using System.Web;
using System.Data.EntityClient;
using SlamCms.SharePoint.Data;
using Microsoft.SharePoint.Client.Services;
using Microsoft.SharePoint.WebControls;
using SlamCms.SharePoint.Core;
using SlamCms.Configuration;
using SlamCms.Data.Repositories;
using SlamCms.Data;
using SlamCms.Common;

namespace SlamCms.SharePoint.Publishing
{
	[ServiceContract(Namespace = "")]
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
	[BasicHttpBindingServiceMetadataExchangeEndpoint]
	[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
    public class CommentsService
	{
		[WebInvoke(Method = "GET",
		ResponseFormat = WebMessageFormat.Json,
        UriTemplate = "GetComments?siteId={siteId}",
		BodyStyle = WebMessageBodyStyle.Bare)]
		[OperationContract]
        public DataTablesServiceResponse GetComments(string siteId)
		{
           
            int echo = int.Parse(HttpContext.Current.Request["sEcho"]);
            int displayStart = int.Parse(HttpContext.Current.Request["iDisplayStart"]);
            int displayLength = int.Parse(HttpContext.Current.Request["iDisplayLength"]);

			CommentRepository repository = new CommentRepository(new DefaultDbConnectionResolver().GetConnection());
            var comments = repository.GetComments(new Guid(siteId));

            IEnumerable<string[]> result = null;

            int totalContentItems = 0;

            if (comments.Count() > 0)
            {
                totalContentItems = comments.Count();

                var userIds = comments.Select(i => i.UserId).Distinct().ToArray();
                var users = SlamCmsContext.Data.Users.Where(u => userIds.Any(i => i.Equals(u.UserId))).ToList();

                var contentItemIds = comments.Select(c => c.ContentItemId).Distinct().ToArray();
                var contentItems = SlamCmsContext.Data.CreateQuery().FilterContentItemId(contentItemIds).Get().ToList();

                var returnComments = new List<ReturnComment>();
                string applicationFrontEndUrl = ConfigurationManager.Environment.DefaultApplication.FrontEndUrl.TrimEnd('/');

                foreach (CommentResource c in comments.Skip(displayStart).Take(displayLength).ToList())
                { 
                    var user = users.Where(u => u.UserId.Equals(c.UserId)).FirstOrDefault();
                    var resource = contentItems.Where(ci => ci.ContentItemId.Equals(c.ContentItemId)).FirstOrDefault();

                    ReturnComment comment = new ReturnComment();
                    comment.createdDate = c.CreatedDate;
                    comment.userName = user != null ? user.Name : String.Empty;
                    comment.text = c.Text;
                    if (resource != null)
                    {
                        comment.resourceUrl = applicationFrontEndUrl + "/link/" + resource.ContentItemId.Replace("-p", String.Empty);
                        comment.resource = resource.ReferenceTitle;
                    }
                    comment.status = c.Status;
                    comment.commentId = c.Status.Equals("Approved") ? c.CommentID.ToString() : String.Empty;

                    returnComments.Add(comment);
                }

                if(returnComments.Count > 0)
                    returnComments = Filter(returnComments);

                if (returnComments.Count > 0)
                    returnComments = ApplyOrder(returnComments);

                if (returnComments.Count > 0)
                    result = from rc in returnComments
                             select new[] { rc.createdDate.ToShortDateString(),
                                            rc.userName,
                                            rc.text,
                                            rc.resourceUrl,
                                            rc.resource,
                                            rc.status,
                                            rc.commentId                            
                             };

            }   

             return new DataTablesServiceResponse
            {
                sEcho = echo,
                iTotalRecords = totalContentItems,
                iTotalDisplayRecords = totalContentItems,
                aaData = (result != null ? result : new List<string[]>())
            };
		}


        private List<ReturnComment> ApplyOrder(List<ReturnComment> comments)
        {
            int sortColumns = !String.IsNullOrEmpty(HttpContext.Current.Request["iSortingCols"]) ? int.Parse(HttpContext.Current.Request["iSortingCols"]) : 0;
            var orderedComments = comments;

            if (sortColumns > 0)
            {
                List<Column> columnsOrder = new List<Column>();
                for (int i = 0; i < sortColumns; i++)
                { 
                    if(!String.IsNullOrEmpty(HttpContext.Current.Request["iSortCol_"+i.ToString()]))
                    {
                        Column col = new Column();
                        col.number = int.Parse(HttpContext.Current.Request["iSortCol_" + i.ToString()]);
                        col.direction = HttpContext.Current.Request["sSortDir_" + i.ToString()];

                        columnsOrder.Add(col);
                    }
                }

                orderedComments = Sort(orderedComments, columnsOrder);
            }
            return orderedComments;
        }

        private List<ReturnComment> Filter(List<ReturnComment> comments)
        {
            var filteredComments = comments;

            string filterDate = HttpContext.Current.Request["sSearch_0"];
            string filterUserName = HttpContext.Current.Request["sSearch_1"];
            string filterText = HttpContext.Current.Request["sSearch_2"];
            string filterResource = HttpContext.Current.Request["sSearch_3"];
            string filterStatus = HttpContext.Current.Request["sSearch_4"];


            if (!String.IsNullOrEmpty(filterUserName))
            {

                filteredComments = (from u in filteredComments
                                   where u.userName.Contains(filterUserName)
                                   select u).ToList();
            }
            if (!String.IsNullOrEmpty(filterText))
            {

                filteredComments = (from u in filteredComments
                                    where u.text.Contains(filterText)
                                    select u).ToList();
            }
            if (!String.IsNullOrEmpty(filterResource))
            {

                filteredComments = (from u in filteredComments
                                    where u.resource.Contains(filterResource)
                                    select u).ToList();
            }
            if (!String.IsNullOrEmpty(filterStatus))
            {

                filteredComments = (from u in filteredComments
                                    where u.status.Contains(filterStatus)
                                    select u).ToList();
            }

            return filteredComments;
        }

        private List<ReturnComment> Sort(List<ReturnComment> comments, List<Column> columnsOrder)
        { 

            //List<ReturnComment> sorted = comments;
            IOrderedEnumerable<ReturnComment> temp = null;
            Func<ReturnComment, object> expression = null;
            
            for(int i = 0; i<columnsOrder.Count;i++)
            {
                Column c = columnsOrder[i];
                
                switch (c.number)
                { 
                    case 0:
                        expression = (item => item.createdDate);
                        break;
                    case 1:
                        expression = (item => item.userName);
                        break;
                    case 2:
                        expression = (item => item.text);
                        break;
                    case 3:
                        expression = (item => item.resource);
                        break;
                    case 5:
                        expression = (item => item.status);
                        break;
                    default:
                        break;
               
                }
                if (i == 0 && expression != null)
                    temp = OrderBy(c.direction, comments, expression);
                else
                    temp = OrderBy(c.direction, comments, expression); ;
            }

            return temp.ToList();
        
        
        }

        private IOrderedEnumerable<ReturnComment> OrderBy(string direction, IOrderedEnumerable<ReturnComment> comments, Func<ReturnComment,object> expression)
        {
           
                if (direction == "asc")
                    return comments.ThenBy(expression);
                else
                    return comments.ThenByDescending(expression);
        }


        private IOrderedEnumerable<ReturnComment> OrderBy(string direction, List<ReturnComment> comments, Func<ReturnComment, object> expression)
        {

            if (direction == "asc")
                return comments.OrderBy(expression);
            else
                return comments.OrderByDescending(expression);

        }

	}

    public class Column
    {
        public int number { get; set; }
        public string direction { get; set; }
    }

    internal class  ReturnComment
    {
        public DateTime createdDate { get; set; }
        public string userName { get; set; }
        public string text { get; set; }
        public string resourceUrl { get; set; }
        public string resource { get; set; }
        public string status { get; set; }
        public string commentId { get; set; }
    }

}
